package ph.edu.ics.sp.graphisched;

import java.awt.Color;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class ClassBox implements GraphiSchedConstants {
	private ArrayList<Point> points = new ArrayList<Point>();
	private ArrayList<ClassBox> laboratories = new ArrayList<ClassBox>();
	private boolean sectionFlags[] = { false, false, false, false, false,
			false, false, false };
	private boolean dayFlags[] = { false, false, false, false, false, false };
	private Course subject;
	private Color color;
	private String section;
	private int height;
	private int width;
	private int ctr;
	private boolean isLecture;
	private String time;
	private String day;
	private ClassBox lectureClass;
	private String room;
	private String teacher;

	/**
	 * default constructor
	 */
	public ClassBox() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param subject
	 * @param color
	 * @param section
	 * @param points
	 * @param height
	 * @param width
	 */
	public ClassBox(Course subject, Color color, Point point, int width,
			boolean isLecture) {
		super();
		this.subject = subject;
		this.color = color;
		this.width = width;
		this.isLecture = isLecture;
		this.setHeight();
		this.setPoints(point);
		this.setTime(point);
		this.setDay();
		if (isLecture) {
			this.setSection();
		}
	}

	public ClassBox(Course subject, Color color, Point point, int width,
			boolean isLecture, String room, String teacher) {
		super();
		this.subject = subject;
		this.color = color;
		this.width = width;
		this.isLecture = isLecture;
		this.room = room;
		this.teacher = teacher;
		this.setHeight();
		this.setPoints(point);
		this.setTime(point);
		this.setDay();
		if (isLecture) {
			this.setSection();
		}
	}

	/**
	 * @return the subject
	 */
	public Course getSubject() {
		return subject;
	}

	/**
	 * @param subject
	 *            the subject to set
	 */
	public void setSubject(Course subject) {
		this.subject = subject;
	}

	/**
	 * @return the color
	 */
	public Color getColor() {
		return color;
	}

	/**
	 * @param color
	 *            the color to set
	 */
	public void setColor(Color color) {
		this.color = color;
	}

	/**
	 * @return the section
	 */
	public String getSection() {
		return section;
	}

	public static ArrayList<ClassBox> sortLaboratories(
			final ArrayList<ClassBox> labSections) {
		Collections.sort(labSections, new Comparator<ClassBox>() {
			public int compare(final ClassBox lab1, final ClassBox lab2) {

				return (lab1.getPoints().get(0).x * 10 * TABLE_PANE_HEIGHT + lab1
						.getPoints().get(0).y)
						- (lab2.getPoints().get(0).x * 10 * TABLE_PANE_HEIGHT + lab2
								.getPoints().get(0).y);
			}
		});

		return labSections;
	}

	/**
	 * @param section
	 *            the section to set
	 */
	public void setSection(String section) {
		this.section = section;
	}

	/**
	 * @param section
	 *            the section to set
	 */
	public void setSection() {
		StringBuffer section = new StringBuffer();
		ClassBox lecClass = this.getLectureClass();
		ArrayList<ClassBox> labs = new ArrayList<ClassBox>();
		try {
			labs = lecClass.getLaboratories();
		} catch (Exception e) {
		}

		// set section for lecture classes
		if (this.isLecture) {
			String[] lettersSet1 = { "A", "B", "C", "D", "E", "F", "G", "H" };
			String[] lettersSet2 = { "S", "T", "U", "V", "W", "X", "Y", "Z" };
			setSectionFlags();
			int ind = 0;
			for (int i = 0; i < 8; i++) {
				if (sectionFlags[i]) {
					if (dayFlags[0] || dayFlags[2] || dayFlags[4]) {
						section.append(lettersSet1[i]);
					} else {
						section.append(lettersSet2[i]);
					}
					ind++;
				} else if (ind != this.ctr && ind != 0) {
					if (dayFlags[0] || dayFlags[2] || dayFlags[4]) {
						section.append(lettersSet1[i]);
					} else {
						section.append(lettersSet2[i]);
					}
				} else if (ind == ctr) {
					break;
				}
			}
			// set section
			this.section = section.toString();
		} else {
			// sort laboratory for sectioning
			labs = sortLaboratories(lecClass.getLaboratories());

		}
		// update lab section
		int size = labs.size();
		for (int i = 0; i < size; i++) {
			section = new StringBuffer();
			section.append(lecClass.getSection());
			section.append("-");
			section.append(i + 1);
			section.append("L");
			labs.get(i).setSection(section.toString());
		}
	}

	/**
	 * sets the corresponding section flag if box is found at TIME_*
	 */
	public void setSectionFlags() {
		int startPt = this.getPoints().get(0).y;
		int endPt = this.getPoints().get(0).y + this.height;
		this.ctr = 0;

		for (int i = 0; i < 8; i++) {
			sectionFlags[i] = false;
		}

		if ((startPt >= TIME_7_730.x && startPt < TIME_830_9.x)
				|| (endPt > TIME_7_730.x && endPt <= TIME_830_9.x)) {
			sectionFlags[0] = true;
			ctr++;
		}
		if ((startPt >= TIME_830_9.x && startPt < TIME_10_1030.x)
				|| (endPt > TIME_830_9.x && endPt <= TIME_10_1030.x)) {
			sectionFlags[1] = true;
			ctr++;
		}
		if ((startPt >= TIME_10_1030.x && startPt < TIME_1130_12.x)
				|| (endPt > TIME_10_1030.x && endPt <= TIME_1130_12.x)) {
			sectionFlags[2] = true;
			ctr++;
		}
		if ((startPt >= TIME_1130_12.x && startPt < TIME_1_130.x)
				|| (endPt > TIME_1130_12.x && endPt <= TIME_1_130.x)) {
			sectionFlags[3] = true;
			ctr++;
		}
		if ((startPt >= TIME_1_130.x && startPt < TIME_230_3.x)
				|| (endPt > TIME_1_130.x && endPt <= TIME_230_3.x)) {
			sectionFlags[4] = true;
			ctr++;
		}
		if ((startPt >= TIME_230_3.x && startPt < TIME_4_430.x)
				|| (endPt > TIME_230_3.x && endPt <= TIME_4_430.x)) {
			sectionFlags[5] = true;
			ctr++;
		}
		if ((startPt >= TIME_4_430.x && startPt < TIME_530_6.x)
				|| (endPt > TIME_4_430.x && endPt <= TIME_530_6.x)) {
			sectionFlags[6] = true;
			ctr++;
		}
		if ((startPt >= TIME_530_6.x && startPt < TIME_630_7.y)
				|| (endPt > TIME_530_6.x && endPt <= TIME_630_7.y)) {
			sectionFlags[7] = true;
			ctr++;
		}
	}

	/**
	 * @return the points
	 */
	public ArrayList<Point> getPoints() {
		return points;
	}

	/**
	 * @param points
	 *            the points to set
	 */
	public void setPoints(ArrayList<Point> points) {
		this.points = points;
	}

	/**
	 * @param points
	 *            the points to set
	 */
	public void setPoints(Point point) {
		ArrayList<Point> points = new ArrayList<Point>();
		int session;
		if (this.isLecture) {
			session = this.subject.getLecSessionsPerWeek();
		} else {
			session = this.subject.getLaboratorySessionsPerWeek();
		}

		switch (point.x) {
		case MON:
			points.add(new Point(MON, point.y));
			if (session > 1 && session < 4) {
				points.add(new Point(WED, point.y));
			}
			if (session == 3) {
				points.add(new Point(FRI, point.y));
			}
			break;
		case TUE:
			points.add(new Point(TUE, point.y));
			if (session > 1 && session < 4) {
				points.add(new Point(THUR, point.y));
			}
			if (session == 3) {
				points.add(new Point(SAT, point.y));
			}
			break;
		case WED:
			points.add(new Point(WED, point.y));
			if (session > 1 && session < 4) {
				points.add(new Point(FRI, point.y));
			}
			if (session == 3) {
				points.add(new Point(MON, point.y));
			}
			break;
		case THUR:
			points.add(new Point(THUR, point.y));
			if (session > 1 && session < 4) {
				points.add(new Point(TUE, point.y));
			}
			if (session == 3) {
				points.add(new Point(SAT, point.y));
			}
			break;
		case FRI:
			points.add(new Point(FRI, point.y));
			if (session > 1 && session < 4) {
				points.add(new Point(WED, point.y));
			}
			if (session == 3) {
				points.add(new Point(MON, point.y));
			}
			break;
		case SAT:
			points.add(new Point(SAT, point.y));
			if (session > 1 && session < 4) {
				points.add(new Point(THUR, point.y));
			}
			if (session == 3) {
				points.add(new Point(TUE, point.y));
			}
		}
		this.points = sortPoints(points);
	}

	public static ArrayList<Point> sortPoints(final ArrayList<Point> points) {
		Collections.sort(points, new Comparator<Point>() {
			public int compare(final Point pt1, final Point pt2) {

				return pt1.x - pt2.x;
			}
		});

		return points;
	}

	/**
	 * @return the height
	 */
	public int getHeight() {
		return height;
	}

	/**
	 * @param height
	 *            the height to set
	 */
	public void setHeight() {
		int height = 0;
		if (this.isLecture) {
			height = (this.subject.getLectureHoursPerWeek() / subject
					.getLecSessionsPerWeek()) * 38;
		} else {
			height = (this.subject.getLaboratoryHoursPerWeek() / subject
					.getLaboratorySessionsPerWeek()) * 38;
		}
		this.height = height;
	}

	/**
	 * @return the width
	 */
	public int getWidth() {
		return width;
	}

	/**
	 * @param width
	 *            the width to set
	 */
	public void setWidth(int width) {
		this.width = width;
	}

	/**
	 * @return the isLecture
	 */
	public boolean getIsLecture() {
		return isLecture;
	}

	/**
	 * @param width
	 *            the width to set
	 */
	public void setIsLecture(boolean isLecture) {
		this.isLecture = isLecture;
	}

	/**
	 * @return the time
	 */
	public String getTime() {
		return time;
	}

	/**
	 * @param time
	 *            the time to set
	 */
	public void setTime(Point point) {
		StringBuffer time = new StringBuffer();
		time.append(getTimeValueUp(point.y));
		time.append("-");
		time.append(getTimeValueDown(point.y + this.height));
		this.time = time.toString();
	}

	public String getTimeValueUp(int pt) {
		String time = new String();
		if (TIME_7_730.x == pt) {
			time = "7:00";
			return time;
		}
		if (TIME_730_8.x == pt) {
			time = "7:30";
			return time;
		}
		if (TIME_8_830.x == pt) {
			time = "8:00";
			return time;
		}
		if (TIME_830_9.x == pt) {
			time = "8:30";
			return time;
		}
		if (TIME_9_930.x == pt) {
			time = "9:00";
			return time;
		}
		if (TIME_930_10.x == pt) {
			time = "9:30";
			return time;
		}
		if (TIME_10_1030.x == pt) {
			time = "10:00";
			return time;
		}
		if (TIME_1030_11.x == pt) {
			time = "10:30";
			return time;
		}
		if (TIME_11_1130.x == pt) {
			time = "11:00";
			return time;
		}
		if (TIME_1130_12.x == pt) {
			time = "11:30";
			return time;
		}
		if (TIME_12_1230.x == pt) {
			time = "12:00";
			return time;
		}
		if (TIME_1230_1.x == pt) {
			time = "12:30";
			return time;
		}
		if (TIME_1_130.x == pt) {
			time = "1:00";
			return time;
		}
		if (TIME_130_2.x == pt) {
			time = "1:30";
			return time;
		}
		if (TIME_2_230.x == pt) {
			time = "2:00";
			return time;
		}
		if (TIME_230_3.x == pt) {
			time = "2:30";
			return time;
		}
		if (TIME_3_330.x == pt) {
			time = "3:00";
			return time;
		}
		if (TIME_330_4.x == pt) {
			time = "3:30";
			return time;
		}
		if (TIME_4_430.x == pt) {
			time = "4:00";
			return time;
		}
		if (TIME_430_5.x == pt) {
			time = "4:30";
			return time;
		}
		if (TIME_5_530.x == pt) {
			time = "5:00";
			return time;
		}
		if (TIME_530_6.x == pt) {
			time = "5:30";
			return time;
		}
		if (TIME_6_630.x == pt) {
			time = "6:00";
			return time;
		}
		if (TIME_630_7.x == pt) {
			time = "6:30";
			return time;
		}

		return time;
	}

	public String getTimeValueDown(int pt) {
		String time = new String();
		if (TIME_7_730.y == pt) {
			time = "7:30";
			return time;
		}
		if (TIME_730_8.y == pt) {
			time = "8:00";
			return time;
		}
		if (TIME_8_830.y == pt) {
			time = "8:30";
			return time;
		}
		if (TIME_830_9.y == pt) {
			time = "9:00";
			return time;
		}
		if (TIME_9_930.y == pt) {
			time = "9:30";
			return time;
		}
		if (TIME_930_10.y == pt) {
			time = "10:00";
			return time;
		}
		if (TIME_10_1030.y == pt) {
			time = "10:30";
			return time;
		}
		if (TIME_1030_11.y == pt) {
			time = "11:00";
			return time;
		}
		if (TIME_11_1130.y == pt) {
			time = "11:30";
			return time;
		}
		if (TIME_1130_12.y == pt) {
			time = "12:00";
			return time;
		}
		if (TIME_12_1230.y == pt) {
			time = "12:30";
			return time;
		}
		if (TIME_1230_1.y == pt) {
			time = "1:00";
			return time;
		}
		if (TIME_1_130.y == pt) {
			time = "1:30";
			return time;
		}
		if (TIME_130_2.y == pt) {
			time = "2:00";
			return time;
		}
		if (TIME_2_230.y == pt) {
			time = "2:30";
			return time;
		}
		if (TIME_230_3.y == pt) {
			time = "3:00";
			return time;
		}
		if (TIME_3_330.y == pt) {
			time = "3:30";
			return time;
		}
		if (TIME_330_4.y == pt) {
			time = "4:00";
			return time;
		}
		if (TIME_4_430.y == pt) {
			time = "4:30";
			return time;
		}
		if (TIME_430_5.y == pt) {
			time = "5:00";
			return time;
		}
		if (TIME_5_530.y == pt) {
			time = "5:30";
			return time;
		}
		if (TIME_530_6.y == pt) {
			time = "6:00";
			return time;
		}
		if (TIME_6_630.y == pt) {
			time = "6:30";
			return time;
		}
		if (TIME_630_7.y == pt) {
			time = "7:00";
			return time;
		}

		return time;
	}

	/**
	 * @return the day
	 */
	public String getDay() {
		return day;
	}

	/**
	 * @param day
	 *            the day to set
	 */
	public void setDay() {
		StringBuffer day = new StringBuffer();
		int size = this.getPoints().size();
		String days[] = { "M", "T", "W", "Th", "F", "S" };
		// initialize flags
		for (int i = 0; i < 6; i++) {
			this.dayFlags[i] = false;
		}
		if (size == 1) {
			int pt = this.getPoints().get(0).x;
			if (pt == MON) {
				day.append("Mon");
				this.dayFlags[0] = true;
			} else if (pt == TUE) {
				day.append("Tue");
				this.dayFlags[1] = true;
			} else if (pt == WED) {
				day.append("Wed");
				this.dayFlags[2] = true;
			} else if (pt == THUR) {
				day.append("Thur");
				this.dayFlags[3] = true;
			} else if (pt == FRI) {
				day.append("Fri");
				this.dayFlags[4] = true;
			} else if (pt == SAT) {
				day.append("Sat");
				this.dayFlags[5] = true;
			}
		} else {
			for (int i = 0; i < size; i++) {
				int pt = this.getPoints().get(i).x;
				if (pt == MON) {
					this.dayFlags[0] = true;
				} else if (pt == TUE) {
					this.dayFlags[1] = true;
				} else if (pt == WED) {
					this.dayFlags[2] = true;
				} else if (pt == THUR) {
					this.dayFlags[3] = true;
				} else if (pt == FRI) {
					this.dayFlags[4] = true;
				} else if (pt == SAT) {
					this.dayFlags[5] = true;
				}
			}
			for (int i = 0; i < 6; i++) {
				if (dayFlags[i]) {
					day.append(days[i]);
				}
			}
		}

		this.day = day.toString();
	}

	public void addLab(ClassBox cb) {
		laboratories.add(cb);
	}

	public void removeLab(ClassBox cb) {
		laboratories.remove(cb);
	}

	public void removeAllLabs() {
		laboratories.clear();
	}

	public ArrayList<ClassBox> getLaboratories() {
		return laboratories;
	}

	public void setLectureClass(ClassBox lecCb) {
		this.lectureClass = lecCb;
	}

	public ClassBox getLectureClass() {
		return lectureClass;
	}

	/**
	 * @return the room
	 */
	public String getRoom() {
		return room;
	}

	/**
	 * @param room
	 *            the room to set
	 */
	public void setRoom(String room) {
		this.room = room;
	}

	/**
	 * @return the teacher
	 */
	public String getTeacher() {
		return teacher;
	}

	/**
	 * @param teacher
	 *            the teacher to set
	 */
	public void setTeacher(String teacher) {
		this.teacher = teacher;
	}

}
